package pap.test.fcPuCc;

import gov.nasa.jpf.jvm.Verify;

import java.util.ArrayList;
import java.util.List;

/*
 * Represent a body composed by a group of simple bodies (>=2).
 */
public class CompoundBody extends Body {

	private List<SimpleBody> bodies;

	/**
	 * Instance a new CompoundBody that contains the bodies within the list.
	 * 
	 * @param bodiesList
	 * @throws UncompatibleDimensionsException
	 */
	public CompoundBody(List<Body> bodiesList) {
		Verify.beginAtomic();
		mass = 0;
		this.bodies = new ArrayList<SimpleBody>();
		for (Body body : bodiesList) {
			addBody(body);
		}
		updateProperties();
		Verify.endAtomic();
	}

	/**
	 * Adds a new body to the component's list. If the new body is a
	 * CompoudBody, add to the list all his components
	 * 
	 * @param body
	 */
	private void addBody(Body body) {
		if (body instanceof CompoundBody) {
			for (SimpleBody b : ((CompoundBody) body).getBodies()) {
				bodies.add(b);
			}
		} else {
			bodies.add((SimpleBody) body);
		}
	}

	/**
	 * When updating position and speed of a compoundBody, is necessary to
	 * update also single components's
	 */
	@Override
	protected void updatePositionAndSpeed(Vector deltaP, Vector deltaV) {
		super.updatePositionAndSpeed(deltaP, deltaV);

		/*
		 * Also the position and speed of the single components must be updated
		 */
		for (SimpleBody body : bodies) {
			body.updatePositionAndSpeed(deltaP, deltaV);
		}
	}

	/**
	 * After adding the bodies to the list, is required to update mass and mass
	 * center.
	 * 
	 * @throws UncompatibleDimensionsException
	 */
	private void updateProperties() {

		int dimension = 2;
		double[] massCenterCoords = new double[dimension];

		Vector speedVector = new Vector(new Point(new double[] { 0, 0 }));

		for (int i = 0; i < dimension; i++) {
			massCenterCoords[i] = 0;
		}

		for (Body body : bodies) {

			mass += body.getMass();

			/*
			 * XofMassCenter = m1X1 + m2X2+...+ mNXN / totalMass and so on for
			 * every coordinate
			 */
			for (int i = 0; i < dimension; i++) {
				massCenterCoords[i] += body.getMassCenter().getCoordinate(i)
						* body.getMass();
			}

			speedVector = speedVector.sum(body.speed.multiply(body.mass));

		}

		for (int i = 0; i < dimension; i++) {
			massCenterCoords[i] /= mass;
		}

		massCenter = new Point(massCenterCoords);

		speed = speedVector.divide(mass);

		for (SimpleBody body : bodies)
			body.speed = speed;
	}

	public List<SimpleBody> getBodies() {
		return bodies;
	}

	/**
	 * A CompoundBody is intersected to another body if at least one of his
	 * components is intersected to this body
	 */
	@Override
	public boolean intersect(SimpleBody body) {
		for (SimpleBody simpleBody : bodies) {
			if (body.intersect(simpleBody))
				return true;
		}

		return false;
	}

}